import abc
from enum import Enum as EnumCLS
from typing import Any, Optional, Type

from tortoise import Model

from fastadmin.widgets.inputs import Input


class Filter(Input):
    """
    Parent class for all filters
    """

    def __init__(self, name: str, label: str, help_text: Optional[str] = None):
        super().__init__(help_text=help_text)
        self.name = name
        self.context.update(label=label, name=name)


class Datetime(Filter):
    template = "widgets/filters/datetime.html"


class Select(Filter):
    @abc.abstractmethod
    async def get_options(self):
        """
        return list of tuple with display and value

        [("on",1),("off",2)]

        :return: list of tuple with display and value
        """

    async def render(self, value: Any):
        options = await self.get_options()
        self.context.update(options=options)
        return await super(Select, self).render(value)


class Enum(Select):
    template = "widgets/filters/enum.html"

    def __init__(
        self,
        enum: Type[EnumCLS],
        name: str,
        label: str,
        help_text: Optional[str] = None,
    ):
        super().__init__(name, label, help_text)
        self.enum = enum

    async def get_options(self):
        return [(v.name, v.value) for v in self.enum]


class ForeignKey(Select):
    def __init__(
        self,
        model: Type[Model],
        name_field: str,
        value_field: str,
        filters: dict,
        name: str,
        label: str,
        help_text: Optional[str] = None,
    ):
        super().__init__(name, label, help_text)
        self.model = model
        self.name_field = name_field
        self.value_field = value_field
        self.filters = filters

    async def get_options(self):
        return await self.model.filter(**self.filters).values_list(
            self.name_field, self.value_field
        )
